package com.hk.Mgr.web.controller.app.yingmi;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.hk.api.ProcessAPI;
import com.hk.api.exceptions.ValidateException;
import com.hk.app.utils.TimeService;
import com.hk.app.utils.YingmiOpenAPI;
import com.hk.base.BaseCtrl;
import com.hk.commons.enm.Whether;
import com.hk.commons.entity.yingmi.YingmiBrokerProduct;
import com.hk.commons.vo.JsonResult;
import com.hk.yingmi.YingmiProductCache;
import com.hk.service.yingmi.YingmiProductService;
import com.hk.yingmi.YingmiOpenAPIConstant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Antinomy on 17/9/26.
 */
@Controller
@RequestMapping(value = BaseCtrl.App)
public class YingmiProductController {

    public static final String brokerProductType = "5";  // 券商产品类型

    private Logger logger = LoggerFactory.getLogger(YingmiProductController.class);

    @Autowired
    private YingmiProductService yingmiProductService;

    @Autowired
    private YingmiProductCache yingmiProductCache;

    @Autowired
    private YingmiOpenAPI openAPI;

    @RequestMapping(value = YingmiOpenAPIConstant.YINGMI_API_PRODUCT_BATCH_UPDATE, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult batchUpdate(HttpServletRequest request) {
        ProcessAPI api = (jsonResult, validate) -> {

            yingmiProductService.storeYingmiLatestProduct();
        };

        return api.process(request);
    }

    @RequestMapping(value = YingmiOpenAPIConstant.YINGMI_API_BROKER_PRODUCT_SYNC, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult syncBrokerProduct(HttpServletRequest request, String fundCode) {
        ProcessAPI api = (jsonResult, validate) -> {

            validate.check("fundCode", fundCode);

            jsonResult.result = syncBrokerProduct(fundCode);
        };

        return api.process(request);
    }

    @RequestMapping(value = YingmiOpenAPIConstant.YINGMI_API_BROKER_PRODUCT_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult list(HttpServletRequest request, String fundCode, Integer curPage, Integer pageSize) {
        ProcessAPI api = (jsonResult, validate) -> {

            List<YingmiBrokerProduct> products = yingmiProductService.listBrokerProduct(fundCode, curPage, pageSize);

            List<HashMap> result = renderProduct(products);

            jsonResult.result = result;
        };

        return api.process(request);
    }

    @RequestMapping(value = YingmiOpenAPIConstant.YINGMI_API_BROKER_PRODUCT_IS_BROKDER_PRODUCT, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult isBrokerProduct(HttpServletRequest request, String fundCode) {
        ProcessAPI api = (jsonResult, validate) -> {

            jsonResult.result = yingmiProductCache.isBrokerProduct(fundCode);

        };

        return api.process(request);
    }

    private List<HashMap> renderProduct(List<YingmiBrokerProduct> products) {
        List<HashMap> result = new ArrayList<>();

        LocalDate today = LocalDate.now();
        String todayStr = today.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        for (YingmiBrokerProduct product : products) {
            HashMap item = new HashMap();

            Whether canBuy;
            item.put("fundCode", product.getFundCode());
            item.put("fundName", product.getFundName());
            item.put("riskLevel5", product.getAmacRisk5Level());
            item.put("rate", product.getExpectedReturnDesc());
            item.put("investmentTerm", product.getDurationDesc());

            canBuy=checkCanBuy(product.getSubscribeOpenDate(),todayStr);

            item.put("canBuy", canBuy.toString());

            result.add(item);
        }

        return result;
    }

    private Whether checkCanBuy(String subscribeOpenDate,String today) {
//        today="2016-01-01";

        if(StringUtils.isBlank(subscribeOpenDate))
            return Whether.NO;

        try {
            ArrayList<HashMap> list = openAPI.convertArrayToList(subscribeOpenDate);

            for(HashMap item :list){
                String begin = item.get("begin").toString();
                String end = item.get("end").toString();

                if(TimeService.isBetweenDate(today,begin,end))
                    return  Whether.YES;
            }


        } catch (IOException e) {
            e.printStackTrace();
            return  Whether.NO;
        }

        return Whether.NO;
    }

    private Map<String, String> getQueryParams(String fundCode) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("fundCode", fundCode);
        return params;
    }

    private YingmiBrokerProduct syncBrokerProduct(String fundCode) throws IOException {
        String fundInfoJson = openAPI.sslGet_ByMap(YingmiOpenAPIConstant.PRODUCT_GET_FUND_INFO, getQueryParams(fundCode), null);

        HashMap fundInfoMap = openAPI.convertToMap(fundInfoJson);

        if (fundInfoMap.get("fundCode") == null
                || fundInfoMap.get("prodType") == null
                || !brokerProductType.equals(fundInfoMap.get("prodType").toString())
                )
            throw new ValidateException("基金数据无效: " + fundCode);

        YingmiBrokerProduct product = new YingmiBrokerProduct();
        product.setFundCode(getNullWhenEmpty(fundInfoMap.get("fundCode")));
        product.setFundFullName(getNullWhenEmpty(fundInfoMap.get("fundFullName")));
        product.setFundName(getNullWhenEmpty(fundInfoMap.get("fundName")));

        product.setProdType(getNullWhenEmpty(fundInfoMap.get("prodType")));
        product.setRisk5Level(getNullWhenEmpty(fundInfoMap.get("risk5Level")));
        product.setAmacRisk5Level(getNullWhenEmpty(fundInfoMap.get("amacRisk5Level")));

        if (fundInfoMap.get("minIndividualSubscribeAmount") != null) {
            product.setMinIndividualSubscribeAmount(
                    getNullWhenEmptyBigDecimal(fundInfoMap.get("minIndividualSubscribeAmount").toString())
            );
        }

        if (fundInfoMap.get("extra") != null) {
            HashMap extraMap = (HashMap) fundInfoMap.get("extra");
            product.setDurationDesc(getNullWhenEmpty(extraMap.get("durationDesc")));
            product.setExpectedReturnDesc(getNullWhenEmpty(extraMap.get("expectedReturnDesc")));
        }

        String qsInfoJson = openAPI.sslGet_ByMap(YingmiOpenAPIConstant.PRODUCT_GET_QSZG_INFO, getQueryParams(fundCode), null);
        HashMap qsInfoMap = openAPI.convertToMap(qsInfoJson);

        if (qsInfoMap.get("fundCode") == null)
            throw new ValidateException("基金数据无效: " + fundCode);

        product.setAllotOpenDate(getJsonFormatString(qsInfoMap.get("allotOpenDate")));
        product.setRedeemOpenDate(getJsonFormatString(qsInfoMap.get("redeemOpenDate")));
        product.setSubscribeOpenDate(getJsonFormatString(qsInfoMap.get("subscribeOpenDate")));


        product = yingmiProductService.storeBrokerProduct(product);
        return product;
    }

    private String getNullWhenEmpty(Object head) {
        return head != null ? head.toString() : null;
    }

    private BigDecimal getNullWhenEmptyBigDecimal(String head) {
        return !StringUtils.isEmpty(head) ? new BigDecimal(head) : null;
    }

    private String getJsonFormatString(Object value) {
        ArrayList list  =  (ArrayList)value;

        ObjectMapper mapper = new ObjectMapper();
        try
        {
            //Convert Map to JSON
            String json = mapper.writeValueAsString(list);

            //Print JSON output
            logger.debug("Covert Json : {} ",json);

            return json;

        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }


}
